const LEN = 10000;
const FLOAT_POOL = new Float32Array(LEN);
for (let i = 0; i < LEN; i++) {
    FLOAT_POOL[i] = Math.random();
}
let idx = 0;
const rats = new Float32Array(100);

/**
 * 随机数及随机选择
 */
class Random {

    /**
     * 在给定范围内取随机浮点值
     * @param from 起始值
     * @param to 结束值
     * @returns 随机浮点值
     */
    public static float(from?: number, to?: number): number {
        const i = from === undefined ? 0 : from;
        const a = to === undefined ? 1 : to;
        const f = Math.min(i, a);
        const d = Math.max(i, a) - f;
        return d * this.base + f;
    }

    /**
     * 在给定范围内取随机整数值
     * @param from 起始值
     * @param to 结束值
     * @returns 随机整数值
     */
    public static int(from: number, to: number): number {
        const f = this.float(from, to) + 0.499;
        return Math.floor(f);
    }

    /**
     * 在给定集合中随机选取
     * @param vs 集合
     * @returns 选取结果
     */
    public static select<T>(...vs: T[]): T {
        const i = this.int(0, vs.length - 1);
        return vs[i];
    }

    /**
     * 从给定集合中随机选取
     * @param vs 集合
     * @param isRemove 是否从集合中移除
     * @returns 选取结果
     */
    public static selectFrom<T>(vs: T[], isRemove?: boolean): T | null {
        if (!vs.length) return null;
        const i = this.int(0, vs.length - 1);
        const tar = vs[i];
        if (isRemove) vs.splice(i, 1);
        return tar;
    }

    /**
     * 在给定集合中按给定的概率随机选取
     * @param vs 目标对象/值和其被选择的概率的集合
     * @returns 选取的对象/值
     */
    public static selectDef<T>(...vs: Array<[T, number]>): T {
        if (vs.length < 2) return vs[0][0];
        if (vs.length > 100) {
            console.error('The number of parameters exceeds the maximum number [100] supported!');
            return vs[0][0];
        }
        let tol = 0;
        for (const v of vs) {
            tol += v[1];
        }
        for (let i = 0; i < vs.length; i++) {
            const v = vs[i];
            rats[i] = i ? (rats[i - 1] + v[1] / tol) : (v[1] / tol);
        }
        const f = this.base;
        for (let i = vs.length - 1; i > 0; i--) {
            if (f >= rats[i - 1]) return vs[i][0];
        }

        return vs[0][0];
    }

    /**
     * 从给定集合中按给定的概率随机选取
     * @param vs 目标对象/值和其被选择的概率的集合
     * @param isRemove 是否从集合中移除
     * @returns 选取的对象/值
     */
    public static selectDefFrom<T>(vs: Array<[T, number]>, isRemove?: boolean): T | null {
        if (!vs.length) return null;
        let tar;
        if (vs.length < 2) {
            tar = vs[0][0];
            if (isRemove) vs.length = 0;
            return tar;
        }
        if (vs.length > 100) {
            console.error('The number of parameters exceeds the maximum number [100] supported!');
            tar = vs[0][0];
            if (isRemove) vs.splice(0, 1);
            return tar;
        }
        let tol = 0;
        for (const v of vs) {
            tol += v[1];
        }
        for (let i = 0; i < vs.length; i++) {
            const v = vs[i];
            rats[i] = i ? (rats[i - 1] + v[1] / tol) : (v[1] / tol);
        }
        const f = this.base;
        for (let i = vs.length - 1; i > 0; i--) {
            if (f >= rats[i - 1]) {
                tar = vs[i][0];
                if (isRemove) vs.splice(i, 1);
                return tar;
            }
        }

        tar = vs[0][0];
        if (isRemove) vs.splice(0, 1);
        return tar;
    }

    /**
     * 依次获取生成的随机值
     * @return 随机值
     */
    private static get base(): number {
        idx++;
        idx = idx >= LEN ? 0 : idx;
        return FLOAT_POOL[idx];
    }

}


export { Random };